package net.vinote.sosa.test;

import net.vinote.sosa.context.support.SosaGenericXmlApplicationContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.support.AbstractContextLoader;
import org.springframework.util.StringUtils;

public class SosaTestApplicationContext extends AbstractContextLoader {
	protected static final Log logger = LogFactory.getLog(SosaTestApplicationContext.class);

	@Override
	public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
				mergedConfig));
		}

		SosaGenericXmlApplicationContext context = new SosaGenericXmlApplicationContext();

		ApplicationContext parent = mergedConfig.getParentApplicationContext();
		if (parent != null) {
			context.setParent(parent);
		}
		prepareContext(context, mergedConfig);
		loadBeanDefinitions(context, mergedConfig);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
		context.refresh();
		context.registerShutdownHook();
		return context;
	}

	@Override
	public ApplicationContext loadContext(String... locations) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Loading ApplicationContext for locations [%s].",
				StringUtils.arrayToCommaDelimitedString(locations)));
		}
		SosaGenericXmlApplicationContext context = new SosaGenericXmlApplicationContext();
		createBeanDefinitionReader(context).loadBeanDefinitions(locations);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
		context.refresh();
		context.registerShutdownHook();
		return context;
	}

	@Override
	protected String getResourceSuffix() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Load bean definitions into the supplied {@link GenericApplicationContext
	 * context} from the locations or classes in the supplied
	 * {@code MergedContextConfiguration}.
	 *
	 * <p>
	 * The default implementation delegates to the {@link BeanDefinitionReader}
	 * returned by
	 * {@link #createBeanDefinitionReader(GenericApplicationContext)} to
	 * {@link BeanDefinitionReader#loadBeanDefinitions(String) load} the bean
	 * definitions.
	 *
	 * <p>
	 * Subclasses must provide an appropriate implementation of
	 * {@link #createBeanDefinitionReader(GenericApplicationContext)}.
	 * Alternatively subclasses may provide a <em>no-op</em> implementation of
	 * {@code createBeanDefinitionReader()} and override this method to provide
	 * a custom strategy for loading or registering bean definitions.
	 *
	 * @param context
	 *            the context into which the bean definitions should be loaded
	 * @param mergedConfig
	 *            the merged context configuration
	 * @see #loadContext(MergedContextConfiguration)
	 * @since 3.1
	 */
	protected void loadBeanDefinitions(SosaGenericXmlApplicationContext context, MergedContextConfiguration mergedConfig) {
		createBeanDefinitionReader(context).loadBeanDefinitions(mergedConfig.getLocations());
	}

	/**
	 * Factory method for creating a new {@link BeanDefinitionReader} for
	 * loading bean definitions into the supplied
	 * {@link GenericApplicationContext context}.
	 *
	 * @param context
	 *            the context for which the {@code BeanDefinitionReader} should
	 *            be created
	 * @return a {@code BeanDefinitionReader} for the supplied context
	 * @see #loadContext(String...)
	 * @see #loadBeanDefinitions
	 * @see BeanDefinitionReader
	 * @since 2.5
	 */
	protected BeanDefinitionReader createBeanDefinitionReader(SosaGenericXmlApplicationContext context) {
		return new XmlBeanDefinitionReader(context);
	}

}
